PostgreSQL Source Code git master
Loading...
Searching...
No Matches
test_regex.c File Reference
#include "postgres.h"
#include "catalog/pg_type_d.h"
#include "funcapi.h"
#include "regex/regex.h"
#include "utils/array.h"
#include "utils/builtins.h"
Include dependency graph for test_regex.c:

Go to the source code of this file.

Data Structures

struct  test_re_flags
 
struct  test_regex_ctx
 

Typedefs

typedef struct test_re_flags test_re_flags
 
typedef struct test_regex_ctx test_regex_ctx
 

Functions

static void test_re_compile (text *text_re, int cflags, Oid collation, regex_t *result_re)
 
static void parse_test_flags (test_re_flags *flags, text *opts)
 
static test_regex_ctxsetup_test_matches (text *orig_str, regex_t *cpattern, test_re_flags *re_flags, Oid collation, bool use_subpatterns)
 
static ArrayTypebuild_test_info_result (regex_t *cpattern, test_re_flags *flags)
 
static ArrayTypebuild_test_match_result (test_regex_ctx *matchctx)
 
 PG_FUNCTION_INFO_V1 (test_regex)
 
Datum test_regex (PG_FUNCTION_ARGS)
 
static bool test_re_execute (regex_t *re, pg_wchar *data, int data_len, int start_search, rm_detail_t *details, int nmatch, regmatch_t *pmatch, int eflags)
 

Variables

 PG_MODULE_MAGIC
 

Typedef Documentation

◆ test_re_flags

◆ test_regex_ctx

Function Documentation

◆ build_test_info_result()

static ArrayType * build_test_info_result ( regex_t cpattern,
test_re_flags flags 
)
static

Definition at line 617 of file test_regex.c.

618{
619 /* Translation data for flag bits in regex_t.re_info */
620 struct infoname
621 {
622 int bit;
623 const char *text;
624 };
625 static const struct infoname infonames[] = {
626 {REG_UBACKREF, "REG_UBACKREF"},
627 {REG_ULOOKAROUND, "REG_ULOOKAROUND"},
628 {REG_UBOUNDS, "REG_UBOUNDS"},
629 {REG_UBRACES, "REG_UBRACES"},
630 {REG_UBSALNUM, "REG_UBSALNUM"},
631 {REG_UPBOTCH, "REG_UPBOTCH"},
632 {REG_UBBS, "REG_UBBS"},
633 {REG_UNONPOSIX, "REG_UNONPOSIX"},
634 {REG_UUNSPEC, "REG_UUNSPEC"},
635 {REG_UUNPORT, "REG_UUNPORT"},
636 {REG_ULOCALE, "REG_ULOCALE"},
637 {REG_UEMPTYMATCH, "REG_UEMPTYMATCH"},
638 {REG_UIMPOSSIBLE, "REG_UIMPOSSIBLE"},
639 {REG_USHORTEST, "REG_USHORTEST"},
640 {0, NULL}
641 };
642 const struct infoname *inf;
643 Datum elems[lengthof(infonames) + 1];
644 int nresults = 0;
645 char buf[80];
646 int dims[1];
647 int lbs[1];
648
649 /* Set up results: first, the number of subexpressions */
650 snprintf(buf, sizeof(buf), "%d", (int) cpattern->re_nsub);
652
653 /* Report individual info bit states */
654 for (inf = infonames; inf->bit != 0; inf++)
655 {
656 if (cpattern->re_info & inf->bit)
657 {
658 if (flags->info & inf->bit)
659 elems[nresults++] = PointerGetDatum(cstring_to_text(inf->text));
660 else
661 {
662 snprintf(buf, sizeof(buf), "unexpected %s!", inf->text);
664 }
665 }
666 else
667 {
668 if (flags->info & inf->bit)
669 {
670 snprintf(buf, sizeof(buf), "missing %s!", inf->text);
672 }
673 }
674 }
675
676 /* And form an array */
677 dims[0] = nresults;
678 lbs[0] = 1;
679 /* XXX: this hardcodes assumptions about the text type */
680 return construct_md_array(elems, NULL, 1, dims, lbs,
681 TEXTOID, -1, false, TYPALIGN_INT);
682}
ArrayType * construct_md_array(Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
#define lengthof(array)
Definition c.h:873
varlena text
Definition c.h:789
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define snprintf
Definition port.h:260
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
uint64_t Datum
Definition postgres.h:70
static int fb(int x)
#define REG_UEMPTYMATCH
Definition regex.h:149
#define REG_UBOUNDS
Definition regex.h:140
#define REG_UIMPOSSIBLE
Definition regex.h:150
#define REG_UPBOTCH
Definition regex.h:143
#define REG_ULOOKAROUND
Definition regex.h:139
#define REG_UBBS
Definition regex.h:144
#define REG_UUNSPEC
Definition regex.h:146
#define REG_UNONPOSIX
Definition regex.h:145
#define REG_UBSALNUM
Definition regex.h:142
#define REG_USHORTEST
Definition regex.h:151
#define REG_ULOCALE
Definition regex.h:148
#define REG_UUNPORT
Definition regex.h:147
#define REG_UBRACES
Definition regex.h:141
#define REG_UBACKREF
Definition regex.h:138
Datum bit(PG_FUNCTION_ARGS)
Definition varbit.c:391
text * cstring_to_text(const char *s)
Definition varlena.c:184

References bit(), buf, construct_md_array(), cstring_to_text(), fb(), test_re_flags::info, lengthof, PointerGetDatum(), REG_UBACKREF, REG_UBBS, REG_UBOUNDS, REG_UBRACES, REG_UBSALNUM, REG_UEMPTYMATCH, REG_UIMPOSSIBLE, REG_ULOCALE, REG_ULOOKAROUND, REG_UNONPOSIX, REG_UPBOTCH, REG_USHORTEST, REG_UUNPORT, REG_UUNSPEC, and snprintf.

Referenced by test_regex().

◆ build_test_match_result()

static ArrayType * build_test_match_result ( test_regex_ctx matchctx)
static

Definition at line 691 of file test_regex.c.

692{
693 char *buf = matchctx->conv_buf;
694 Datum *elems = matchctx->elems;
695 bool *nulls = matchctx->nulls;
696 bool indices = matchctx->re_flags.indices;
697 char bufstr[80];
698 int dims[1];
699 int lbs[1];
700 int loc;
701 int i;
702
703 /* Extract matching substrings from the original string */
704 loc = matchctx->next_match * matchctx->npatterns * 2;
705 for (i = 0; i < matchctx->npatterns; i++)
706 {
707 int so = matchctx->match_locs[loc++];
708 int eo = matchctx->match_locs[loc++];
709
710 if (indices)
711 {
712 /* Report eo this way for consistency with Tcl */
713 snprintf(bufstr, sizeof(bufstr), "%d %d",
714 so, so < 0 ? eo : eo - 1);
716 nulls[i] = false;
717 }
718 else if (so < 0 || eo < 0)
719 {
720 elems[i] = (Datum) 0;
721 nulls[i] = true;
722 }
723 else if (buf)
724 {
725 int len = pg_wchar2mb_with_len(matchctx->wide_str + so,
726 buf,
727 eo - so);
728
729 Assert(len < matchctx->conv_bufsiz);
731 nulls[i] = false;
732 }
733 else
734 {
736 PointerGetDatum(matchctx->orig_str),
737 Int32GetDatum(so + 1),
738 Int32GetDatum(eo - so));
739 nulls[i] = false;
740 }
741 }
742
743 /* In EXPECT indices mode, also report the "details" */
744 if (indices && (matchctx->re_flags.cflags & REG_EXPECT))
745 {
746 int so = matchctx->details.rm_extend.rm_so;
747 int eo = matchctx->details.rm_extend.rm_eo;
748
749 snprintf(bufstr, sizeof(bufstr), "%d %d",
750 so, so < 0 ? eo : eo - 1);
752 nulls[i] = false;
753 i++;
754 }
755
756 /* And form an array */
757 dims[0] = i;
758 lbs[0] = 1;
759 /* XXX: this hardcodes assumptions about the text type */
760 return construct_md_array(elems, nulls, 1, dims, lbs,
761 TEXTOID, -1, false, TYPALIGN_INT);
762}
#define Assert(condition)
Definition c.h:943
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition fmgr.h:688
int i
Definition isn.c:77
int pg_wchar2mb_with_len(const pg_wchar *from, char *to, int len)
Definition mbutils.c:1019
const void size_t len
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
#define REG_EXPECT
Definition regex.h:191
Datum text_substr(PG_FUNCTION_ARGS)
Definition varlena.c:553
text * cstring_to_text_with_len(const char *s, int len)
Definition varlena.c:196

References Assert, buf, construct_md_array(), cstring_to_text(), cstring_to_text_with_len(), DirectFunctionCall3, fb(), i, Int32GetDatum(), len, pg_wchar2mb_with_len(), PointerGetDatum(), REG_EXPECT, snprintf, and text_substr().

Referenced by test_regex().

◆ parse_test_flags()

static void parse_test_flags ( test_re_flags flags,
text opts 
)
static

Definition at line 248 of file test_regex.c.

249{
250 /* these defaults must match Tcl's */
251 int cflags = REG_ADVANCED;
252 int eflags = 0;
253 long info = 0;
254
255 flags->glob = false;
256 flags->indices = false;
257 flags->partial = false;
258
259 if (opts)
260 {
261 char *opt_p = VARDATA_ANY(opts);
263 int i;
264
265 for (i = 0; i < opt_len; i++)
266 {
267 switch (opt_p[i])
268 {
269 case '-':
270 /* allowed, no-op */
271 break;
272 case '!':
273 flags->partial = true;
274 break;
275 case '*':
276 /* test requires Unicode --- ignored here */
277 break;
278 case '0':
279 flags->indices = true;
280 break;
281
282 /* These flags correspond to user-exposed RE options: */
283 case 'g': /* global match */
284 flags->glob = true;
285 break;
286 case 'i': /* case insensitive */
287 cflags |= REG_ICASE;
288 break;
289 case 'n': /* \n affects ^ $ . [^ */
290 cflags |= REG_NEWLINE;
291 break;
292 case 'p': /* ~Perl, \n affects . [^ */
293 cflags |= REG_NLSTOP;
294 cflags &= ~REG_NLANCH;
295 break;
296 case 'w': /* weird, \n affects ^ $ only */
297 cflags &= ~REG_NLSTOP;
298 cflags |= REG_NLANCH;
299 break;
300 case 'x': /* expanded syntax */
301 cflags |= REG_EXPANDED;
302 break;
303
304 /* These flags correspond to Tcl's -xflags options: */
305 case 'a':
306 cflags |= REG_ADVF;
307 break;
308 case 'b':
309 cflags &= ~REG_ADVANCED;
310 break;
311 case 'c':
312
313 /*
314 * Tcl calls this TCL_REG_CANMATCH, but it's really
315 * REG_EXPECT. In this implementation we must also set
316 * the partial and indices flags, so that
317 * setup_test_matches and build_test_match_result will
318 * emit the desired data. (They'll emit more fields than
319 * Tcl would, but that's fine.)
320 */
321 cflags |= REG_EXPECT;
322 flags->partial = true;
323 flags->indices = true;
324 break;
325 case 'e':
326 cflags &= ~REG_ADVANCED;
327 cflags |= REG_EXTENDED;
328 break;
329 case 'q':
330 cflags &= ~REG_ADVANCED;
331 cflags |= REG_QUOTE;
332 break;
333 case 'o': /* o for opaque */
334 cflags |= REG_NOSUB;
335 break;
336 case 's': /* s for start */
337 cflags |= REG_BOSONLY;
338 break;
339 case '+':
340 cflags |= REG_FAKE;
341 break;
342 case ',':
343 cflags |= REG_PROGRESS;
344 break;
345 case '.':
346 cflags |= REG_DUMP;
347 break;
348 case ':':
349 eflags |= REG_MTRACE;
350 break;
351 case ';':
352 eflags |= REG_FTRACE;
353 break;
354 case '^':
355 eflags |= REG_NOTBOL;
356 break;
357 case '$':
358 eflags |= REG_NOTEOL;
359 break;
360 case 't':
361 cflags |= REG_EXPECT;
362 break;
363 case '%':
364 eflags |= REG_SMALL;
365 break;
366
367 /* These flags define expected info bits: */
368 case 'A':
369 info |= REG_UBSALNUM;
370 break;
371 case 'B':
372 info |= REG_UBRACES;
373 break;
374 case 'E':
375 info |= REG_UBBS;
376 break;
377 case 'H':
378 info |= REG_ULOOKAROUND;
379 break;
380 case 'I':
381 info |= REG_UIMPOSSIBLE;
382 break;
383 case 'L':
384 info |= REG_ULOCALE;
385 break;
386 case 'M':
387 info |= REG_UUNPORT;
388 break;
389 case 'N':
390 info |= REG_UEMPTYMATCH;
391 break;
392 case 'P':
393 info |= REG_UNONPOSIX;
394 break;
395 case 'Q':
396 info |= REG_UBOUNDS;
397 break;
398 case 'R':
399 info |= REG_UBACKREF;
400 break;
401 case 'S':
402 info |= REG_UUNSPEC;
403 break;
404 case 'T':
405 info |= REG_USHORTEST;
406 break;
407 case 'U':
408 info |= REG_UPBOTCH;
409 break;
410
411 default:
414 errmsg("invalid regular expression test option: \"%.*s\"",
416 opt_p + i)));
417 break;
418 }
419 }
420 }
421 flags->cflags = cflags;
422 flags->eflags = eflags;
423 flags->info = info;
424}
int errcode(int sqlerrcode)
Definition elog.c:874
#define ERROR
Definition elog.h:40
#define ereport(elevel,...)
Definition elog.h:152
int pg_mblen_range(const char *mbstr, const char *end)
Definition mbutils.c:1084
static char * errmsg
static AmcheckOptions opts
Definition pg_amcheck.c:112
#define REG_ICASE
Definition regex.h:184
#define REG_DUMP
Definition regex.h:193
#define REG_PROGRESS
Definition regex.h:195
#define REG_ADVANCED
Definition regex.h:181
#define REG_MTRACE
Definition regex.h:206
#define REG_EXPANDED
Definition regex.h:186
#define REG_FTRACE
Definition regex.h:205
#define REG_NLANCH
Definition regex.h:188
#define REG_EXTENDED
Definition regex.h:179
#define REG_NLSTOP
Definition regex.h:187
#define REG_ADVF
Definition regex.h:180
#define REG_SMALL
Definition regex.h:207
#define REG_NOTEOL
Definition regex.h:203
#define REG_NOTBOL
Definition regex.h:202
#define REG_NEWLINE
Definition regex.h:189
#define REG_NOSUB
Definition regex.h:185
#define REG_BOSONLY
Definition regex.h:192
#define REG_FAKE
Definition regex.h:194
#define REG_QUOTE
Definition regex.h:182
static Size VARSIZE_ANY_EXHDR(const void *PTR)
Definition varatt.h:472
static char * VARDATA_ANY(const void *PTR)
Definition varatt.h:486

References test_re_flags::cflags, test_re_flags::eflags, ereport, errcode(), errmsg, ERROR, fb(), test_re_flags::glob, i, test_re_flags::indices, test_re_flags::info, opts, test_re_flags::partial, pg_mblen_range(), REG_ADVANCED, REG_ADVF, REG_BOSONLY, REG_DUMP, REG_EXPANDED, REG_EXPECT, REG_EXTENDED, REG_FAKE, REG_FTRACE, REG_ICASE, REG_MTRACE, REG_NEWLINE, REG_NLANCH, REG_NLSTOP, REG_NOSUB, REG_NOTBOL, REG_NOTEOL, REG_PROGRESS, REG_QUOTE, REG_SMALL, REG_UBACKREF, REG_UBBS, REG_UBOUNDS, REG_UBRACES, REG_UBSALNUM, REG_UEMPTYMATCH, REG_UIMPOSSIBLE, REG_ULOCALE, REG_ULOOKAROUND, REG_UNONPOSIX, REG_UPBOTCH, REG_USHORTEST, REG_UUNPORT, REG_UUNSPEC, VARDATA_ANY(), and VARSIZE_ANY_EXHDR().

Referenced by test_regex().

◆ PG_FUNCTION_INFO_V1()

PG_FUNCTION_INFO_V1 ( test_regex  )

◆ setup_test_matches()

static test_regex_ctx * setup_test_matches ( text orig_str,
regex_t cpattern,
test_re_flags re_flags,
Oid  collation,
bool  use_subpatterns 
)
static

Definition at line 434 of file test_regex.c.

438{
441 int orig_len;
442 pg_wchar *wide_str;
443 int wide_len;
444 regmatch_t *pmatch;
445 int pmatch_len;
446 int array_len;
447 int array_idx;
448 int prev_match_end;
449 int start_search;
450 int maxlen = 0; /* largest fetch length in characters */
451
452 /* save flags */
453 matchctx->re_flags = *re_flags;
454
455 /* save original string --- we'll extract result substrings from it */
456 matchctx->orig_str = orig_str;
457
458 /* convert string to pg_wchar form for matching */
459 orig_len = VARSIZE_ANY_EXHDR(orig_str);
460 wide_str = palloc_array(pg_wchar, orig_len + 1);
461 wide_len = pg_mb2wchar_with_len(VARDATA_ANY(orig_str), wide_str, orig_len);
462
463 /* do we want to remember subpatterns? */
464 if (use_subpatterns && cpattern->re_nsub > 0)
465 {
466 matchctx->npatterns = cpattern->re_nsub + 1;
467 pmatch_len = cpattern->re_nsub + 1;
468 }
469 else
470 {
471 use_subpatterns = false;
472 matchctx->npatterns = 1;
473 pmatch_len = 1;
474 }
475
476 /* temporary output space for RE package */
478
479 /*
480 * the real output space (grown dynamically if needed)
481 *
482 * use values 2^n-1, not 2^n, so that we hit the limit at 2^28-1 rather
483 * than at 2^27
484 */
485 array_len = re_flags->glob ? 255 : 31;
486 matchctx->match_locs = palloc_array(int, array_len);
487 array_idx = 0;
488
489 /* search for the pattern, perhaps repeatedly */
490 prev_match_end = 0;
491 start_search = 0;
492 while (test_re_execute(cpattern, wide_str, wide_len,
494 &matchctx->details,
495 pmatch_len, pmatch,
496 re_flags->eflags))
497 {
498 /* enlarge output space if needed */
499 while (array_idx + matchctx->npatterns * 2 + 1 > array_len)
500 {
501 array_len += array_len + 1; /* 2^n-1 => 2^(n+1)-1 */
502 if (array_len > MaxAllocSize / sizeof(int))
505 errmsg("too many regular expression matches")));
506 matchctx->match_locs = (int *) repalloc(matchctx->match_locs,
507 sizeof(int) * array_len);
508 }
509
510 /* save this match's locations */
511 for (int i = 0; i < matchctx->npatterns; i++)
512 {
513 int so = pmatch[i].rm_so;
514 int eo = pmatch[i].rm_eo;
515
516 matchctx->match_locs[array_idx++] = so;
517 matchctx->match_locs[array_idx++] = eo;
518 if (so >= 0 && eo >= 0 && (eo - so) > maxlen)
519 maxlen = (eo - so);
520 }
521 matchctx->nmatches++;
522 prev_match_end = pmatch[0].rm_eo;
523
524 /* if not glob, stop after one match */
525 if (!re_flags->glob)
526 break;
527
528 /*
529 * Advance search position. Normally we start the next search at the
530 * end of the previous match; but if the match was of zero length, we
531 * have to advance by one character, or we'd just find the same match
532 * again.
533 */
535 if (pmatch[0].rm_so == pmatch[0].rm_eo)
536 start_search++;
538 break;
539 }
540
541 /*
542 * If we had no match, but "partial" and "indices" are set, emit the
543 * details.
544 */
545 if (matchctx->nmatches == 0 && re_flags->partial && re_flags->indices)
546 {
547 /* enlarge output space if needed */
548 while (array_idx + matchctx->npatterns * 2 + 1 > array_len)
549 {
550 array_len += array_len + 1; /* 2^n-1 => 2^(n+1)-1 */
551 if (array_len > MaxAllocSize / sizeof(int))
554 errmsg("too many regular expression matches")));
555 matchctx->match_locs = (int *) repalloc(matchctx->match_locs,
556 sizeof(int) * array_len);
557 }
558
559 matchctx->match_locs[array_idx++] = matchctx->details.rm_extend.rm_so;
560 matchctx->match_locs[array_idx++] = matchctx->details.rm_extend.rm_eo;
561 /* we don't have pmatch data, so emit -1 */
562 for (int i = 1; i < matchctx->npatterns; i++)
563 {
564 matchctx->match_locs[array_idx++] = -1;
565 matchctx->match_locs[array_idx++] = -1;
566 }
567 matchctx->nmatches++;
568 }
569
570 Assert(array_idx <= array_len);
571
572 if (eml > 1)
573 {
574 int64 maxsiz = eml * (int64) maxlen;
575 int conv_bufsiz;
576
577 /*
578 * Make the conversion buffer large enough for any substring of
579 * interest.
580 *
581 * Worst case: assume we need the maximum size (maxlen*eml), but take
582 * advantage of the fact that the original string length in bytes is
583 * an upper bound on the byte length of any fetched substring (and we
584 * know that len+1 is safe to allocate because the varlena header is
585 * longer than 1 byte).
586 */
587 if (maxsiz > orig_len)
588 conv_bufsiz = orig_len + 1;
589 else
590 conv_bufsiz = maxsiz + 1; /* safe since maxsiz < 2^30 */
591
592 matchctx->conv_buf = palloc(conv_bufsiz);
593 matchctx->conv_bufsiz = conv_bufsiz;
594 matchctx->wide_str = wide_str;
595 }
596 else
597 {
598 /* No need to keep the wide string if we're in a single-byte charset. */
599 pfree(wide_str);
600 matchctx->wide_str = NULL;
601 matchctx->conv_buf = NULL;
602 matchctx->conv_bufsiz = 0;
603 }
604
605 /* Clean up temp storage */
606 pfree(pmatch);
607
608 return matchctx;
609}
int64_t int64
Definition c.h:621
#define MaxAllocSize
Definition fe_memutils.h:22
#define palloc_array(type, count)
Definition fe_memutils.h:76
#define palloc0_object(type)
Definition fe_memutils.h:75
unsigned int pg_wchar
Definition mbprint.c:31
int pg_database_encoding_max_length(void)
Definition mbutils.c:1672
int pg_mb2wchar_with_len(const char *from, pg_wchar *to, int len)
Definition mbutils.c:997
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
#define regmatch_t
Definition regex.h:246
static bool test_re_execute(regex_t *re, pg_wchar *data, int data_len, int start_search, rm_detail_t *details, int nmatch, regmatch_t *pmatch, int eflags)
Definition test_regex.c:200

References Assert, test_re_flags::eflags, ereport, errcode(), errmsg, ERROR, fb(), test_re_flags::glob, i, test_re_flags::indices, MaxAllocSize, palloc(), palloc0_object, palloc_array, test_re_flags::partial, pfree(), pg_database_encoding_max_length(), pg_mb2wchar_with_len(), regmatch_t, repalloc(), test_re_execute(), VARDATA_ANY(), and VARSIZE_ANY_EXHDR().

Referenced by test_regex().

◆ test_re_compile()

static void test_re_compile ( text text_re,
int  cflags,
Oid  collation,
regex_t result_re 
)
static

Definition at line 159 of file test_regex.c.

161{
164 pg_wchar *pattern;
165 int pattern_len;
166 int regcomp_result;
167 char errMsg[100];
168
169 /* Convert pattern string to wide characters */
170 pattern = (pg_wchar *) palloc((text_re_len + 1) * sizeof(pg_wchar));
172 pattern,
174
176 pattern,
178 cflags,
179 collation);
180
181 pfree(pattern);
182
184 {
185 /* re didn't compile (no need for pg_regfree, if so) */
186 pg_regerror(regcomp_result, result_re, errMsg, sizeof(errMsg));
189 errmsg("invalid regular expression: %s", errMsg)));
190 }
191}
int pg_regcomp(regex_t *re, const chr *string, size_t len, int flags, Oid collation)
Definition regcomp.c:372
size_t pg_regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
Definition regerror.c:60
#define REG_OKAY
Definition regex.h:215

References ereport, errcode(), errmsg, ERROR, fb(), palloc(), pfree(), pg_mb2wchar_with_len(), pg_regcomp(), pg_regerror(), REG_OKAY, VARDATA_ANY(), and VARSIZE_ANY_EXHDR().

Referenced by test_regex().

◆ test_re_execute()

static bool test_re_execute ( regex_t re,
pg_wchar data,
int  data_len,
int  start_search,
rm_detail_t details,
int  nmatch,
regmatch_t pmatch,
int  eflags 
)
static

Definition at line 200 of file test_regex.c.

205{
206 int regexec_result;
207 char errMsg[100];
208
209 /* Initialize match locations in case engine doesn't */
210 details->rm_extend.rm_so = -1;
211 details->rm_extend.rm_eo = -1;
212 for (int i = 0; i < nmatch; i++)
213 {
214 pmatch[i].rm_so = -1;
215 pmatch[i].rm_eo = -1;
216 }
217
218 /* Perform RE match and return result */
220 data,
221 data_len,
223 details,
224 nmatch,
225 pmatch,
226 eflags);
227
229 {
230 /* re failed??? */
231 pg_regerror(regexec_result, re, errMsg, sizeof(errMsg));
234 errmsg("regular expression failed: %s", errMsg)));
235 }
236
237 return (regexec_result == REG_OKAY);
238}
const void * data
#define REG_NOMATCH
Definition regex.h:216
int pg_regexec(regex_t *re, const chr *string, size_t len, size_t search_start, rm_detail_t *details, size_t nmatch, regmatch_t pmatch[], int flags)
Definition regexec.c:185
pg_regoff_t rm_eo
Definition regex.h:164
pg_regoff_t rm_so
Definition regex.h:163
pg_regmatch_t rm_extend
Definition regex.h:170

References data, ereport, errcode(), errmsg, ERROR, fb(), i, pg_regerror(), pg_regexec(), REG_NOMATCH, REG_OKAY, pg_regmatch_t::rm_eo, rm_detail_t::rm_extend, and pg_regmatch_t::rm_so.

Referenced by setup_test_matches().

◆ test_regex()

Datum test_regex ( PG_FUNCTION_ARGS  )

Definition at line 80 of file test_regex.c.

81{
85
86 if (SRF_IS_FIRSTCALL())
87 {
88 text *pattern = PG_GETARG_TEXT_PP(0);
89 text *flags = PG_GETARG_TEXT_PP(2);
90 Oid collation = PG_GET_COLLATION();
91 test_re_flags re_flags;
93 MemoryContext oldcontext;
94
96 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
97
98 /* Determine options */
99 parse_test_flags(&re_flags, flags);
100
101 /* set up the compiled pattern */
102 test_re_compile(pattern, re_flags.cflags, collation, &cpattern);
103
104 /* be sure to copy the input string into the multi-call ctx */
106 &re_flags,
107 collation,
108 true);
109
110 /* Pre-create workspace that build_test_match_result needs */
111 matchctx->elems = palloc_array(Datum, matchctx->npatterns + 1);
112 matchctx->nulls = palloc_array(bool, matchctx->npatterns + 1);
113
114 MemoryContextSwitchTo(oldcontext);
115 funcctx->user_fctx = matchctx;
116
117 /*
118 * Return the first result row, which is info equivalent to Tcl's
119 * "regexp -about" output
120 */
122
124
126 }
127 else
128 {
129 /* Each subsequent row describes one match */
131 matchctx = (test_regex_ctx *) funcctx->user_fctx;
132
133 if (matchctx->next_match < matchctx->nmatches)
134 {
136 matchctx->next_match++;
138 }
139 }
140
142}
#define PG_GETARG_TEXT_PP(n)
Definition fmgr.h:310
#define PG_GET_COLLATION()
Definition fmgr.h:198
#define PG_GETARG_TEXT_P_COPY(n)
Definition fmgr.h:316
#define SRF_IS_FIRSTCALL()
Definition funcapi.h:304
#define SRF_PERCALL_SETUP()
Definition funcapi.h:308
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition funcapi.h:310
#define SRF_FIRSTCALL_INIT()
Definition funcapi.h:306
#define SRF_RETURN_DONE(_funcctx)
Definition funcapi.h:328
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
unsigned int Oid
#define regex_t
Definition regex.h:245
void pg_regfree(regex_t *re)
Definition regfree.c:49
Definition c.h:776
static test_regex_ctx * setup_test_matches(text *orig_str, regex_t *cpattern, test_re_flags *re_flags, Oid collation, bool use_subpatterns)
Definition test_regex.c:434
static void test_re_compile(text *text_re, int cflags, Oid collation, regex_t *result_re)
Definition test_regex.c:159
static ArrayType * build_test_match_result(test_regex_ctx *matchctx)
Definition test_regex.c:691
static void parse_test_flags(test_re_flags *flags, text *opts)
Definition test_regex.c:248
static ArrayType * build_test_info_result(regex_t *cpattern, test_re_flags *flags)
Definition test_regex.c:617

References build_test_info_result(), build_test_match_result(), test_re_flags::cflags, fb(), MemoryContextSwitchTo(), palloc_array, parse_test_flags(), PG_GET_COLLATION, PG_GETARG_TEXT_P_COPY, PG_GETARG_TEXT_PP, pg_regfree(), PointerGetDatum(), regex_t, setup_test_matches(), SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, and test_re_compile().

Variable Documentation

◆ PG_MODULE_MAGIC

PG_MODULE_MAGIC

Definition at line 23 of file test_regex.c.