41 #define PG_GETARG_TEXT_PP_IF_EXISTS(_n) \
42 (PG_NARGS() > (_n) ? PG_GETARG_TEXT_PP(_n) : NULL)
95 #ifndef MAX_CACHED_RES
96 #define MAX_CACHED_RES 32
118 bool use_subpatterns,
119 bool ignore_degenerate,
120 bool fetching_unmatched);
156 if (
re_array[
i].cre_pat_len == text_re_len &&
158 re_array[
i].cre_collation == collation &&
159 memcmp(
re_array[
i].cre_pat, text_re_val, text_re_len) == 0)
208 (
errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
209 errmsg(
"invalid regular expression: %s", errMsg)));
223 (
errcode(ERRCODE_OUT_OF_MEMORY),
224 errmsg(
"out of memory")));
226 memcpy(re_temp.
cre_pat, text_re_val, text_re_len);
268 int start_search,
int nmatch,
regmatch_t *pmatch)
287 pg_regerror(regexec_result, re, errMsg,
sizeof(errMsg));
289 (
errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
290 errmsg(
"regular expression failed: %s", errMsg)));
293 return (regexec_result ==
REG_OKAY);
345 int cflags,
Oid collation,
357 return RE_execute(re, dat, dat_len, nmatch, pmatch);
383 for (
i = 0;
i < opt_len;
i++)
430 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
431 errmsg(
"invalid regular expression option: \"%.*s\"",
595 so = pmatch[1].
rm_so;
596 eo = pmatch[1].
rm_eo;
601 so = pmatch[0].
rm_so;
602 eo = pmatch[0].
rm_eo;
611 if (so < 0 || eo < 0)
663 if (*opt_p >=
'0' && *opt_p <=
'9')
665 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
666 errmsg(
"invalid regular expression option: \"%.*s\"",
668 errhint(
"If you meant to use regexp_replace() with a start parameter, cast the fourth argument to integer explicitly.")));
675 0, flags.
glob ? 0 : 1));
701 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
702 errmsg(
"invalid value for parameter \"%s\": %d",
710 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
711 errmsg(
"invalid value for parameter \"%s\": %d",
720 n = re_flags.
glob ? 0 : 1;
761 bool afterescape =
false;
762 bool incharclass =
false;
767 if (esc_text == NULL)
783 if (escape_mblen > 1)
785 (
errcode(ERRCODE_INVALID_ESCAPE_SEQUENCE),
786 errmsg(
"invalid escape string"),
787 errhint(
"Escape string must be empty or one character.")));
867 else if (
e && elen == mblen && memcmp(
e, p, mblen) == 0)
893 if (pchar ==
'"' && !incharclass)
907 else if (nquotes == 1)
921 (
errcode(ERRCODE_INVALID_USE_OF_ESCAPE_CHARACTER),
922 errmsg(
"SQL regular expression may not contain more than two escape-double-quote separators")));
937 else if (
e && pchar == *
e)
942 else if (incharclass)
950 else if (pchar ==
'[')
955 else if (pchar ==
'%')
960 else if (pchar ==
'_')
962 else if (pchar ==
'(')
969 else if (pchar ==
'\\' || pchar ==
'.' ||
970 pchar ==
'^' || pchar ==
'$')
1067 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1068 errmsg(
"invalid value for parameter \"%s\": %d",
1077 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1079 errmsg(
"%s does not support the \"global\" option",
1080 "regexp_count()")));
1082 re_flags.
glob =
true;
1131 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1132 errmsg(
"invalid value for parameter \"%s\": %d",
1140 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1141 errmsg(
"invalid value for parameter \"%s\": %d",
1147 if (endoption != 0 && endoption != 1)
1149 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1150 errmsg(
"invalid value for parameter \"%s\": %d",
1151 "endoption", endoption)));
1158 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1159 errmsg(
"invalid value for parameter \"%s\": %d",
1160 "subexpr", subexpr)));
1168 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1170 errmsg(
"%s does not support the \"global\" option",
1171 "regexp_instr()")));
1173 re_flags.
glob =
true;
1255 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1257 errmsg(
"%s does not support the \"global\" option",
1294 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1296 errmsg(
"%s does not support the \"global\" option",
1298 errhint(
"Use the regexp_matches function instead.")));
1349 true,
false,
false);
1405 bool use_subpatterns,
1406 bool ignore_degenerate,
1407 bool fetching_unmatched)
1421 int prev_valid_match_end;
1433 cflags = re_flags->
cflags;
1434 if (!use_subpatterns)
1439 if (use_subpatterns && cpattern->
re_nsub > 0)
1442 pmatch_len = cpattern->
re_nsub + 1;
1446 use_subpatterns =
false;
1460 array_len = re_flags->
glob ? 255 : 31;
1466 prev_valid_match_end = 0;
1468 pmatch_len, pmatch))
1475 if (!ignore_degenerate ||
1476 (pmatch[0].rm_so < wide_len &&
1477 pmatch[0].rm_eo > prev_match_end))
1480 while (array_idx + matchctx->
npatterns * 2 + 1 > array_len)
1482 array_len += array_len + 1;
1485 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1486 errmsg(
"too many regular expression matches")));
1488 sizeof(
int) * array_len);
1492 if (use_subpatterns)
1498 int so = pmatch[
i].
rm_so;
1499 int eo = pmatch[
i].
rm_eo;
1503 if (so >= 0 && eo >= 0 && (eo - so) > maxlen)
1509 int so = pmatch[0].
rm_so;
1510 int eo = pmatch[0].
rm_eo;
1514 if (so >= 0 && eo >= 0 && (eo - so) > maxlen)
1524 if (fetching_unmatched &&
1525 pmatch[0].rm_so >= 0 &&
1526 (pmatch[0].rm_so - prev_valid_match_end) > maxlen)
1527 maxlen = (pmatch[0].rm_so - prev_valid_match_end);
1528 prev_valid_match_end = pmatch[0].
rm_eo;
1530 prev_match_end = pmatch[0].
rm_eo;
1533 if (!re_flags->
glob)
1542 start_search = prev_match_end;
1543 if (pmatch[0].rm_so == pmatch[0].rm_eo)
1545 if (start_search > wide_len)
1553 if (fetching_unmatched &&
1554 (wide_len - prev_valid_match_end) > maxlen)
1555 maxlen = (wide_len - prev_valid_match_end);
1565 int64 maxsiz = eml * (int64) maxlen;
1578 if (maxsiz > orig_len)
1579 conv_bufsiz = orig_len + 1;
1581 conv_bufsiz = maxsiz + 1;
1610 bool *nulls = matchctx->
nulls;
1623 if (so < 0 || eo < 0)
1634 Assert(len < matchctx->conv_bufsiz);
1653 TEXTOID, -1,
false, TYPALIGN_INT);
1682 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1684 errmsg(
"%s does not support the \"global\" option",
1685 "regexp_split_to_table()")));
1687 re_flags.
glob =
true;
1737 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1739 errmsg(
"%s does not support the \"global\" option",
1740 "regexp_split_to_array()")));
1742 re_flags.
glob =
true;
1788 elog(
ERROR,
"invalid match ending position");
1792 elog(
ERROR,
"invalid match starting position");
1801 Assert(len < splitctx->conv_bufsiz);
1838 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1839 errmsg(
"invalid value for parameter \"%s\": %d",
1847 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1848 errmsg(
"invalid value for parameter \"%s\": %d",
1856 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1857 errmsg(
"invalid value for parameter \"%s\": %d",
1858 "subexpr", subexpr)));
1866 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1868 errmsg(
"%s does not support the \"global\" option",
1869 "regexp_substr()")));
1871 re_flags.
glob =
true;
1895 if (so < 0 || eo < 0)
1955 if (case_insensitive)
1980 pg_regerror(re_result, re, errMsg,
sizeof(errMsg));
1982 (
errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
1983 errmsg(
"regular expression failed: %s", errMsg)));
1989 result = (
char *)
palloc(maxlen);
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Datum makeArrayResult(ArrayBuildState *astate, MemoryContext rcontext)
ArrayType * construct_md_array(Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
elog(ERROR, "%s: %s", p2, msg)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
#define PG_GETARG_TEXT_PP(n)
#define PG_GETARG_NAME(n)
#define PG_RETURN_TEXT_P(x)
#define PG_RETURN_INT32(x)
#define PG_GETARG_INT32(n)
#define PG_RETURN_DATUM(x)
#define DirectFunctionCall3(func, arg1, arg2, arg3)
#define PG_GET_COLLATION()
#define PG_GETARG_TEXT_P_COPY(n)
#define PG_RETURN_BOOL(x)
#define SRF_IS_FIRSTCALL()
#define SRF_PERCALL_SETUP()
#define SRF_RETURN_NEXT(_funcctx, _result)
#define SRF_FIRSTCALL_INIT()
#define SRF_RETURN_DONE(_funcctx)
if(TABLE==NULL||TABLE_index==NULL)
Assert(fmt[strlen(fmt) - 1] !='\n')
int pg_mbstrlen_with_len(const char *mbstr, int limit)
int pg_wchar2mb_with_len(const pg_wchar *from, char *to, int len)
int pg_database_encoding_max_length(void)
int pg_mb2wchar_with_len(const char *from, pg_wchar *to, int len)
int pg_mblen(const char *mbstr)
void pfree(void *pointer)
void * palloc0(Size size)
MemoryContext CurrentMemoryContext
void * repalloc(void *pointer, Size size)
#define CHECK_FOR_INTERRUPTS()
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
static AmcheckOptions opts
static XLogRecPtr startpos
static Datum PointerGetDatum(const void *X)
static Datum Int32GetDatum(int32 X)
int pg_regcomp(regex_t *re, const chr *string, size_t len, int flags, Oid collation)
size_t pg_regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
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)
struct regexp_matches_ctx regexp_matches_ctx
Datum regexp_match_no_flags(PG_FUNCTION_ARGS)
Datum textregexreplace(PG_FUNCTION_ARGS)
Datum texticregexne(PG_FUNCTION_ARGS)
Datum regexp_substr_no_start(PG_FUNCTION_ARGS)
struct pg_re_flags pg_re_flags
Datum regexp_split_to_array(PG_FUNCTION_ARGS)
Datum texticregexeq(PG_FUNCTION_ARGS)
Datum regexp_substr_no_n(PG_FUNCTION_ARGS)
Datum regexp_instr_no_subexpr(PG_FUNCTION_ARGS)
Datum similar_to_escape_2(PG_FUNCTION_ARGS)
bool RE_compile_and_execute(text *text_re, char *dat, int dat_len, int cflags, Oid collation, int nmatch, regmatch_t *pmatch)
static bool RE_wchar_execute(regex_t *re, pg_wchar *data, int data_len, int start_search, int nmatch, regmatch_t *pmatch)
Datum regexp_substr(PG_FUNCTION_ARGS)
Datum nameicregexne(PG_FUNCTION_ARGS)
Datum textregexsubstr(PG_FUNCTION_ARGS)
static Datum build_regexp_split_result(regexp_matches_ctx *splitctx)
Datum regexp_split_to_array_no_flags(PG_FUNCTION_ARGS)
Datum textregexreplace_extended_no_n(PG_FUNCTION_ARGS)
static regexp_matches_ctx * setup_regexp_matches(text *orig_str, text *pattern, pg_re_flags *re_flags, int start_search, Oid collation, bool use_subpatterns, bool ignore_degenerate, bool fetching_unmatched)
Datum nameregexne(PG_FUNCTION_ARGS)
Datum regexp_instr(PG_FUNCTION_ARGS)
static ArrayType * build_regexp_match_result(regexp_matches_ctx *matchctx)
Datum similar_to_escape_1(PG_FUNCTION_ARGS)
Datum regexp_substr_no_flags(PG_FUNCTION_ARGS)
Datum regexp_matches(PG_FUNCTION_ARGS)
static text * similar_escape_internal(text *pat_text, text *esc_text)
#define PG_GETARG_TEXT_PP_IF_EXISTS(_n)
Datum nameicregexeq(PG_FUNCTION_ARGS)
Datum regexp_matches_no_flags(PG_FUNCTION_ARGS)
Datum regexp_split_to_table_no_flags(PG_FUNCTION_ARGS)
Datum regexp_match(PG_FUNCTION_ARGS)
Datum textregexreplace_extended(PG_FUNCTION_ARGS)
Datum nameregexeq(PG_FUNCTION_ARGS)
Datum regexp_instr_no_n(PG_FUNCTION_ARGS)
Datum regexp_count_no_start(PG_FUNCTION_ARGS)
struct cached_re_str cached_re_str
regex_t * RE_compile_and_cache(text *text_re, int cflags, Oid collation)
static cached_re_str re_array[MAX_CACHED_RES]
static bool RE_execute(regex_t *re, char *dat, int dat_len, int nmatch, regmatch_t *pmatch)
static void parse_re_flags(pg_re_flags *flags, text *opts)
char * regexp_fixed_prefix(text *text_re, bool case_insensitive, Oid collation, bool *exact)
Datum regexp_split_to_table(PG_FUNCTION_ARGS)
Datum textregexreplace_noopt(PG_FUNCTION_ARGS)
Datum regexp_like_no_flags(PG_FUNCTION_ARGS)
Datum regexp_instr_no_flags(PG_FUNCTION_ARGS)
Datum textregexeq(PG_FUNCTION_ARGS)
Datum textregexne(PG_FUNCTION_ARGS)
Datum regexp_count_no_flags(PG_FUNCTION_ARGS)
Datum similar_escape(PG_FUNCTION_ARGS)
Datum regexp_instr_no_start(PG_FUNCTION_ARGS)
Datum regexp_instr_no_endoption(PG_FUNCTION_ARGS)
Datum textregexreplace_extended_no_flags(PG_FUNCTION_ARGS)
Datum regexp_like(PG_FUNCTION_ARGS)
Datum regexp_substr_no_subexpr(PG_FUNCTION_ARGS)
Datum regexp_count(PG_FUNCTION_ARGS)
void pg_regfree(regex_t *re)
int pg_regprefix(regex_t *re, chr **string, size_t *slength)
MemoryContext multi_call_memory_ctx
#define SET_VARSIZE(PTR, len)
#define VARSIZE_ANY_EXHDR(PTR)
Datum text_substr(PG_FUNCTION_ARGS)
text * cstring_to_text_with_len(const char *s, int len)
text * replace_text_regexp(text *src_text, text *pattern_text, text *replace_text, int cflags, Oid collation, int search_start, int n)